import { getStorage, StorageKey } from '@/config/sessions';
import { commonConfig, momentFormat, userRoleCfg, userRoleMap } from "@/config/common";
import { commonString, msgCode, msgContent } from '@/config/string';
import axios from 'axios';
import jsBeautify from 'js-beautify';
import {Message, MessageBox, Notification} from 'element-ui';
import moment from "moment";
import { WidgetFactory } from "@/modules/IDE/widgetFactory";
import {assetBaseUrl} from "@/config/env";
import {directionData} from "@/config/ide/common";
// 当前user信息
export function getUserInfo() {
  const role = getStorage(StorageKey.role);
  return {
    userId: getStorage(StorageKey.userId),
    token: getStorage(StorageKey.token),
    username: getStorage(StorageKey.username),
    name: getStorage(StorageKey.name),
    nickname: getStorage(StorageKey.nickname),
    tel: getStorage(StorageKey.tel),
    email: getStorage(StorageKey.email),
    role: getStorage(StorageKey.role),
    roleText: userRoleMap[role] || commonString.unknown,
    isAdmin: getStorage(StorageKey.isAdmin),
  };
}

const eleMsgType = {
  success: 'success',
  warning: 'warning',
  error: 'error'
};

export function messageHandle(option = {}) {
  const {
    code, type = '', title = '', msg = '',
    duration = 2500, dangerHTML = false
  } = option;
  let msgType = eleMsgType.success;
  let dftMsg = '';

  switch (code) {
    case msgCode.SUCCESS:
      msgType = eleMsgType.success;
      dftMsg = msgContent.SUCCESS;
      break;
    case msgCode.ADD_SUCCESS:
      msgType = eleMsgType.success;
      dftMsg = msgContent.ADD_SUCCESS;
      break;
    case msgCode.SYNC_SUCCESS:
      msgType = eleMsgType.success;
      dftMsg = msgContent.SYNC_SUCCESS;
      break;
    case msgCode.EDIT_SUCCESS:
      msgType = eleMsgType.success;
      dftMsg = msgContent.EDIT_SUCCESS;
      break;
    case msgCode.DELETE_SUCCESS:
      msgType = eleMsgType.success;
      dftMsg = msgContent.DELETE_SUCCESS;
      break;
    case msgCode.OPERATE_SUCCESS:
      msgType = eleMsgType.success;
      dftMsg = msgContent.OPERATE_SUCCESS;
      break;
    case msgCode.SAVE_SUCCESS:
      msgType = eleMsgType.success;
      dftMsg = msgContent.SAVE_SUCCESS;
      break;
    case msgCode.UPLOAD_SUCCESS:
      msgType = eleMsgType.success;
      dftMsg = msgContent.UPLOAD_SUCCESS;
      break;
    case msgCode.DOWNLOAD_SUCCESS:
      msgType = eleMsgType.success;
      dftMsg = msgContent.DOWNLOAD_SUCCESS;
      break;
    case msgCode.COPY_SUCCESS:
      msgType = eleMsgType.success;
      dftMsg = msgContent.COPY_SUCCESS;
      break;
    case msgCode.ERROR:
      msgType = eleMsgType.error;
      dftMsg = msgContent.ERROR;
      break;
    case msgCode.ADD_ERROR:
      msgType = eleMsgType.error;
      dftMsg = msgContent.ADD_ERROR;
      break;
    case msgCode.EDIT_ERROR:
      msgType = eleMsgType.error;
      dftMsg = msgContent.EDIT_ERROR;
      break;
    case msgCode.DELETE_ERROR:
      msgType = eleMsgType.error;
      dftMsg = msgContent.DELETE_ERROR;
      break;
    case msgCode.OPERATE_ERROR:
      msgType = eleMsgType.error;
      dftMsg = msgContent.OPERATE_ERROR;
      break;
    case msgCode.SAVE_ERROR:
      msgType = eleMsgType.error;
      dftMsg = msgContent.SAVE_ERROR;
      break;
    case msgCode.UPLOAD_ERROR:
      msgType = eleMsgType.error;
      dftMsg = msgContent.UPLOAD_ERROR;
      break;
    case msgCode.DOWNLOAD_ERROR:
      msgType = eleMsgType.error;
      dftMsg = msgContent.DOWNLOAD_ERROR;
      break;
    case msgCode.LOGIN_ERROR:
      msgType = eleMsgType.error;
      dftMsg = msgContent.LOGIN_ERROR;
      break;
    default:
      break;
  }
  Notification({
    type: type || msgType,
    title: '提示',
    message: msg || `${title}${dftMsg}!`,
    duration: duration,
    dangerouslyUseHTMLString: dangerHTML
  });
}

// 取消回车事件的弹窗处理
export function confirmHandle(config = {}) {
  const {
    title = '提示', label = '', confirmText = '确认', cancelText = '取消',
    preventDefaultClose = false, isHtml = false
  } = config;
  // preventDefaultClose: 阻止默认的关闭事件，不显示关闭按钮，禁止点击 modal、escape 键
  return new Promise((resolve, reject) => {
    MessageBox.confirm(label, title, {
      confirmButtonText: confirmText,
      cancelButtonText: cancelText,
      showClose: !preventDefaultClose,
      closeOnClickModal: !preventDefaultClose,
      closeOnPressEscape: !preventDefaultClose,
      distinguishCancelAndClose: !preventDefaultClose,
      dangerouslyUseHTMLString: isHtml,
      zIndex: 3000,
      beforeClose: (action, instance, done) => {
        // 取消回车确认事件
        if (action === 'confirm') {
          instance.$refs['confirm'].$el.onclick = ((e) => {
            e = e || window.event;
            if (e.detail !== 0) {
              done();
            }
          })();
        } else {
          done();
        }
      }
    }).then(() => resolve()).catch((action) => reject(action));
  });
}

// 新窗口打开页面
export function windowOpenNewPage(self, param = {}) {
  let route = self.$router.resolve(param);
  window.open(route.href, '_blank');
}

// 扁平结构转树形结构
export function assembleTreeFromArray(options) {
  const {
    srcData = [], parentKey = 'pid', childKey = 'id', labelKey = 'name',
    createProperty = false, filter = false, sort = true, single = false
  } = options;
  const map = {};
  let node;
  const tree = [];
  let i;
  // 先根据 sortNo 排序
  sort && srcData.sort((a, b) => {return a.sortNo - b.sortNo});
  for (i = 0; i < srcData.length; i++) {
    map[srcData[i][childKey]] = srcData[i];
    srcData[i].children = [];
  }
  for (i = 0; i < srcData.length; i += 1) {
    node = srcData[i];
    if (createProperty) {
      node.label = node[labelKey];
      node.value = node[childKey];
    }

    if (
      node[parentKey] &&
      map[node[parentKey]] &&
      map[node[parentKey]].children
    ) {
      map[node[parentKey]].children.push(node);
    } else {
      tree.push(node);
    }
  }
  filter && filterEmptyChildren(tree);
  return !single ? tree : tree[0];
}

// 递归去除子级为空的 children 字段
function filterEmptyChildren(srcData = []) {
  srcData.forEach((s) => {
    if (s.children && s.children.length > 0) {
      filterEmptyChildren(s.children);
    } else {
      delete s['children'];
    }
  });
}

export function isJsonString(str) {
  try {
    if (typeof JSON.parse(str) === 'object') {
      return true;
    }
  } catch (e) {
    return false;
  }
  return false;
}

export function JSONParse(str = '') {
  try {
    return JSON.parse(str);
  } catch (e) {
    return '';
  }
}

// 通过 JSON.stringify 转化 判断相等
export function judgeEqualByJson(obj1, obj2) {
  return JSON.stringify(obj1) === JSON.stringify(obj2);
}

// 利用 JSON 深度拷贝
export function deepCopyWithJson(src = {}) {
  return JSON.parse(JSON.stringify(src));
}

function checkType(any) {
  return Object.prototype.toString.call(any).slice(8, -1);
}

export function deepCopy(any) {
  if (checkType(any) === 'Object') {
    // 拷贝对象
    const o = {};
    for (const key in any) {
      o[key] = deepCopy(any[key]);
    }
    return o;
  } else if (checkType(any) === 'Array') {
    // 拷贝数组
    const arr = [];
    for (let i = 0, length = any.length; i < length; i++) {
      arr[i] = deepCopy(any[i]);
    }
    return arr;
  } else if (checkType(any) === 'Function') {
    // 拷贝函数
    return new Function('return ' + any.toString()).call(this);
  } else if (checkType(any) === 'Date') {
    // 拷贝日期
    return new Date(any.valueOf());
  } else if (checkType(any) === 'RegExp') {
    // 拷贝正则
    return new RegExp(any);
  } else if (checkType(any) === 'Map') {
    // 拷贝Map 集合
    const m = new Map();
    any.forEach((v, k) => {
      m.set(k, deepCopy(v));
    });
    return m;
  } else if (checkType(any) === 'Set') {
    // 拷贝Set 集合
    const s = new Set();
    for (const val of any.values()) {
      s.add(deepCopy(val));
    }
    return s;
  }
  return any;
}

// 判断字符串/数字相等
export function judgeStrEqual(str1 = '', str2 = '') {
  return str1 + '' === str2 + '';
}

// 判断两个对象是否相等（仅平级结构）
export function flatObjEqual(obj1 = {}, obj2 = {}) {
  let equal = true;
  Object.keys(obj1).forEach(k => { // 遍历obj1中所有可枚举属性
    !judgeStrEqual(obj1[k], obj2[k]) && (equal = false); // judgeStrEqual(obj1[k], obj2[k])判断两对象的每个属性值是否相等，相等(取反为false)=>equal=false
  });
  Object.keys(obj2).forEach(k => { // 遍历obj2中所有可枚举属性
    !judgeStrEqual(obj1[k], obj2[k]) && (equal = false);
  });
  return equal;
}

// 强转为字符串
export function forceToString(src = '') {
  return src + '';
}

// 判断两数组是否相互包含
export function judgeArrayContain(arr1 = [], arr2 = [], ordered = false) {
  if (!ordered) {
    const intersection = _.intersection(arr1, arr2); // 取arr1和arr2的交集
    return intersection.length === arr1.length || intersection.length === arr2.length;
  } else {
    let contain = true;
    for (let i = 0; i < arr1.length; i++) { // 判断数组是否相互包含(arr2包含arr1)
      const ele1 = arr1[i];
      const ele2 = arr2[i];
      if (ele1 !== ele2) {
        contain = false;
        break;
      }
    }
    if (contain) return contain;
    contain = true;
    for (let i = 0; i < arr2.length; i++) { // arr1包含arr2
      const ele1 = arr1[i];
      const ele2 = arr2[i];
      if (ele1 !== ele2) {
        contain = false;
        break;
      }
    }
    return contain;
  }
}

// 生成随机 ID
export function generateUID(len = 16, radix = '') {
  const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
  const uuid = [];
  let i;
  radix = radix || chars.length;

  if (len) {
    // Compact form
    for (i = 0; i < len; i++) uuid[i] = chars[0 | (Math.random() * radix)];
  } else {
    // rfc4122, version 4 form
    let r;

    // rfc4122 requires these characters
    uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
    uuid[14] = '4';

    // Fill in random data.  At i==19 set the high bits of clock sequence as
    // per rfc4122, sec. 4.1.5
    for (i = 0; i < 36; i++) {
      if (!uuid[i]) {
        r = 0 | (Math.random() * 16);
        uuid[i] = chars[i === 19 ? (r & 0x3) | 0x8 : r];
      }
    }
  }

  return uuid.join('');
}

// 将 &#xe77a 格式字符串转化为 html 编码
export function transStrToHtmlDecode(str = '') {
  if (!str) return;
  return str.replace(/&#(x)?([^&]{1,5});?/g, function ($, $1, $2) {
    return String.fromCharCode(parseInt($2, $1 ? 16 : 10));
  });
}

// 拷贝元素文本
export function copyDomText(value = '', showMsg = true) {
  return new Promise((resolve, reject) => {
    if (value) {
      const input = document.createElement('input'); // 直接构建input
      input.value = value; // 设置内容
      document.body.appendChild(input); // 添加临时实例
      input.select(); // 选择实例内容
      document.execCommand('Copy'); // 执行复制
      document.body.removeChild(input); // 删除临时实例
      showMsg && Message({message: '复制成功！', type: 'success'});
      resolve();
    } else {
      reject();
    }
  });
}

// 数组根据字母正序排序
export function sortByAlphabet(key = '') {
  return (el1, el2) => {
    const a = key ? el1[key].toLowerCase() : el1.toLowerCase();
    const b = key ? el2[key].toLowerCase() : el2.toLowerCase();
    if (a < b) return -1;
    if (a > b) return 1;
  };
}

export function arraySortByKey(data = [], sortKey = '', sortType = 'asc') {
  return data.sort((a, b) => {
    const val1 = a[sortKey];
    const val2 = b[sortKey];
    if (val1 > val2) {
      return sortType === 'asc' ? 1 : -1
    } else if (val1 < val2) {
      return sortType === 'asc' ? -1 : 1
    } else {
      return 0
    }
  })
}

// 下载导出文件
export function downloadExportData(data, filename) {
  const blob = dataURItoBlob(data)
  const objectUrl = URL.createObjectURL(blob);
  const aLink = document.createElement('a');//新添加的  尝试
  const evt = document.createEvent("HTMLEvents");
  evt.initEvent("click", true, true);
  aLink.download = filename; // 文件名，需加后缀
  aLink.href = objectUrl;
  aLink.click()
}

// 转换Blob数据流
function dataURItoBlob(dataURI) {
  const byteString = atob(dataURI.split(',')[0]); //base64 解码
  const arrayBuffer = new ArrayBuffer(byteString.length); //创建缓冲数组
  const intArray = new Uint8Array(arrayBuffer); //创建视图
  for (let i = 0; i < byteString.length; i++) {
    intArray[i] = byteString.charCodeAt(i);
  }
  return new Blob([intArray], { type: "application/octet-stream;charset=utf-8;" });//修改-1
}

// 下载附件(通过调用接口的方式)
export function downloadFileApi(url, params = {}) {
  if (!url) return;
  const userInfo = getUserInfo();
  axios({
    url: url,
    method: 'post',
    data: params,
    responseType: 'blob', // 一定要加上 responseType 值为blob
    headers: {
      'token': userInfo.token,
      'userId': userInfo.userId,
    }
  }).then(data => {
    if (!data) return;
    const str = data.headers['content-disposition']
    const site = str.lastIndexOf("\=");
    //截取最后一个/后的值
    const decodeURI1 = str.substring(site + 1, str.length) ? str.substring(site + 1, str.length) : 'EZControlApp.zip'
    const url = window.URL.createObjectURL(data.data);
    const link = document.createElement('a');
    link.style.display = 'none';
    link.href = url;
    // const name = data.headers['content-disposition'].split(';')[1].split('=')[1] || '';// 获取headers里面的文件名称
    link.setAttribute('download', decodeURIComponent(decodeURI1));// download 属性定义了文件名称，并且是必填，不然会页面会自动识别为跳转路径，而不是文件下载地址
    document.body.appendChild(link);
    link.click();
    // 销毁添加的a标签
    setTimeout(() => {
      link.parentNode.removeChild(link);
    }, 200);
  }).catch(err => {
    console.log('err: ', err);
  });
}

export function editorConfigPreview(query = {}) {
  const {type = '', roomId = '', componentId = ''} = query;
  const {protocol = '', host = ''} = window.location;
  let assetsApi = '';
  switch (type) {
    case 'room':
      assetsApi = `${assetBaseUrl}/roomConfig/download/preview/assets?roomId=${roomId}`;
      break;
    case 'component':
      assetsApi = `${assetBaseUrl}/componentConfig/download/preview/assets?componentId=${componentId}`;
      break;
    default:
      break;
  }
  const url = `${protocol + "//" + host}/web/app?assetsApi=${assetsApi}`;
  // const url = `${protocol + "//" + host}/VR/index.html`;
  window.open(url, '_blank');
}

// 导出 Excel
export function exportToExcel(data = [], header = [], fileName = '', sheetName = '') {
  if (!data.length) return;
  const destData = [];
  data.forEach(dt => {
    const item = {};
    header.forEach(h => {
      const { key = '', label = '' } = h;
      item[label] = dt[key] || '';
    });
    destData.push(item);
  });
  // 新建空 workbook，然后加入 worksheet
  const ws = XLSX.utils.json_to_sheet(destData);
  // 新建 book
  const wb = XLSX.utils.book_new();
  // 生成 xlsx 文件 (book, sheet数据, sheet命名)
  XLSX.utils.book_append_sheet(wb, ws, sheetName);
  // 写文件 (book, xlsx文件名称)
  XLSX.writeFile(wb, `${fileName}.xlsx`);
}

export function formatJsCode(str) {
  return jsBeautify.js(str, { indent_size: 2, space_in_empty_paren: true });
}

export function formatColor(val, themeConfig) {
  const colorCfg = themeConfig.find((item) => {
    return item.key === val
  }) || {};
  return colorCfg.value || val
}

export function formatHttpParams(params) {
  return JSON.parse(JSON.stringify(params, (key, value) => {
    if (typeof value === 'string') {
      return encodeURIComponent(value)
    }
    return value
  }))
}

// base64 转化成 file 文件形式
export function base64toFile(base64) {
  let binary = atob(base64.split(",")[1]);
  let array = [];
  for (let i = 0; i < binary.length; i++) {
    array.push(binary.charCodeAt(i));
  }
  return new Blob([new Uint8Array(array)], { type: 'image/png' });
}

// 格式化条目的基本meta信息
export function formatMeta({ createdAt, createdByName, lastUpdatedAt, lastUpdatedByName }) {
  return {
    createdAt: '创建时间: ' + moment(createdAt).format(momentFormat.dateTimeDetail),
    createdAtFromNow: moment(createdAt).fromNow(),
    lastUpdatedAt: '更新时间: ' + moment(lastUpdatedAt).format(momentFormat.dateTimeDetail),
    lastUpdatedAtFromNow: moment(lastUpdatedAt).fromNow(),
    createdByName: '创建人: ' + (createdByName || commonString.system),
    lastUpdatedByName: '更新人: ' + (lastUpdatedByName || commonString.system),
  }
}

// table 列文本映射
export function tableTextColumnMap(data = '', config = {}) {
  const columnText = config.find(ct => {
    return ct.value === data
  }) || {};
  return columnText.label || commonString.unknown
}

// 命令标签解析
export function dealWithModelProtocol(model = '') {
  const pattern = new RegExp(/(\[).*?(\])/g);
  const array = model.match(pattern) || [];
  const modelList = array.map(initItem => {
    let item = initItem.slice(1, initItem.length - 1);
    let resObj = {};

    // 处理设备内置变量，依赖于 webAdmin 上配置的参数
    const varPattern = new RegExp(/(\%).*?(\%)/g);
    const varArray = item.match(varPattern);
    if (varArray && varArray.length) {
      let varItem = item.slice(1, item.length - 1);
      if (~varItem.indexOf('$') && ~varItem.indexOf('|')) {
        const hexSeparatorList = varItem.split('|');
        resObj['data'] = initItem;
        resObj['key'] = hexSeparatorList[0].slice(1, hexSeparatorList[0].length);
        resObj['type'] = commonConfig.codeTagType.instanceVariable;
        resObj['codeStyle'] = commonConfig.codingStyle.hex;
        resObj['length'] = (hexSeparatorList[1] === '?') ? hexSeparatorList[1] : parseInt(hexSeparatorList[1]);
        return resObj;
      }

      if (~varItem.indexOf('@') && ~varItem.indexOf('|')) {
        const asciiSeparatorList = varItem.split('|');
        resObj['data'] = initItem;
        resObj['key'] = asciiSeparatorList[0].slice(1, asciiSeparatorList[0].length);
        resObj['type'] = commonConfig.codeTagType.instanceVariable;
        resObj['codeStyle'] = commonConfig.codingStyle.ascii;
        resObj['length'] = asciiSeparatorList[1];
        return resObj;
      }
    }

    if (item.includes(':')) {
      const separatorList = item.split(':');
      let value = '';
      separatorList.forEach((item, newIdx) => {
        if (newIdx === 1) {
          value = item;
        }
        if (newIdx > 1) {
          value = value + ':' + item;
        }
      });
      switch (separatorList[0]) {
        case commonConfig.specialTags.headAscii:
          resObj['value'] = value;
          resObj['length'] = value.length;
          resObj['type'] = commonConfig.codeTagType.head;
          resObj['codeStyle'] = commonConfig.codingStyle.ascii;
          break;
        case commonConfig.specialTags.headHex:
          resObj['value'] = value;
          resObj['length'] = value.length;
          resObj['type'] = commonConfig.codeTagType.head;
          resObj['codeStyle'] = commonConfig.codingStyle.hex;
          break;
        case commonConfig.specialTags.separateAscii:
          resObj['value'] = value;
          resObj['length'] = value.length;
          resObj['type'] = commonConfig.codeTagType.separate;
          resObj['codeStyle'] = commonConfig.codingStyle.ascii;
          break;
        case commonConfig.specialTags.separateHex:
          resObj['value'] = value;
          resObj['length'] = value.length;
          resObj['type'] = commonConfig.codeTagType.separate;
          resObj['codeStyle'] = commonConfig.codingStyle.hex;
          break;
        case commonConfig.specialTags.terminalAscii:
          resObj['value'] = value;
          resObj['length'] = value.length;
          resObj['type'] = commonConfig.codeTagType.terminal;
          resObj['codeStyle'] = commonConfig.codingStyle.ascii;
          break;
        case commonConfig.specialTags.terminalHex:
          resObj['value'] = value;
          resObj['length'] = value.length;
          resObj['type'] = commonConfig.codeTagType.terminal;
          resObj['codeStyle'] = commonConfig.codingStyle.hex;
          break;
        case commonConfig.specialTags.proxyAddress:
          resObj['value'] = value;
          resObj['length'] = value.length;
          resObj['type'] = commonConfig.codeTagType.proxy;
          resObj['codeStyle'] = commonConfig.codingStyle.ascii;
          break;
        case commonConfig.specialTags.separateBinary:
          resObj['value'] = value;
          resObj['length'] = value.length;
          resObj['type'] = commonConfig.codeTagType.separate;
          resObj['codeStyle'] = commonConfig.codingStyle.binary;
          break;
        default:
          console.log("#### error : 出现未知标签 = ####", separatorList[0]);
          break;
      }
      return resObj;
    }
    switch (item) {
      case commonConfig.specialTags.timeStamp:
        resObj['value'] = initItem;
        resObj['key'] = initItem;
        resObj['type'] = commonConfig.codeTagType.system;
        resObj['length'] = resObj['value'].length;
        resObj['codeStyle'] = commonConfig.codingStyle.ascii;
        return resObj;
      case commonConfig.specialTags.time:
        resObj['value'] = initItem;
        resObj['key'] = initItem;
        resObj['type'] = commonConfig.codeTagType.system;
        resObj['length'] = resObj['value'].length;
        resObj['codeStyle'] = commonConfig.codingStyle.ascii;
        return resObj;
      case commonConfig.specialTags.date:
        resObj['value'] = initItem;
        resObj['key'] = initItem;
        resObj['type'] = commonConfig.codeTagType.system;
        resObj['length'] = resObj['value'].length;
        resObj['codeStyle'] = commonConfig.codingStyle.ascii;
        return resObj;
      default:
        break;
    }

    if (item.includes(commonConfig.specialTags.nLoop) && item.includes('|')) {
      const npSeparatorList = item.split('|');
      resObj['value'] = initItem;
      resObj['key'] = npSeparatorList[0];
      resObj['type'] = commonConfig.codeTagType.nLoop;
      resObj['length'] = parseInt(npSeparatorList[1]);
      resObj['codeStyle'] = commonConfig.codingStyle.hex;
      return resObj;
    }

    // todo ADR 标签在设备库不属于变量
    if (item.includes('ADR')) {
      const newSeparatorList = item.split('|');
      resObj['value'] = initItem;
      resObj['key'] = newSeparatorList[0];
      resObj['type'] = commonConfig.codeTagType.address;
      resObj['codeStyle'] = commonConfig.codingStyle.hex;
      resObj['length'] = (newSeparatorList[1] !== '?') ? (parseInt(newSeparatorList[1]) * 2)
        : parseInt(newSeparatorList[1]);
      return resObj;
    }

    if (item.includes('$') && item.includes('|')) {
      const newSeparatorList = item.split('|');
      resObj['value'] = initItem;
      resObj['key'] = newSeparatorList[0];
      resObj['type'] = commonConfig.codeTagType.variable;
      resObj['codeStyle'] = (newSeparatorList[0].includes('B')) ? commonConfig.codingStyle.binary : commonConfig.codingStyle.hex;
      resObj['length'] = (newSeparatorList[1] !== '?' && (!newSeparatorList[0].includes('B'))) ? (parseInt(newSeparatorList[1]) * 2)
        : parseInt(newSeparatorList[1]);
      return resObj;
    }

    if (item.includes('@') && item.includes('|')) {
      const newSeparatorList = item.split('|');
      resObj['value'] = initItem;
      resObj['key'] = newSeparatorList[0];
      resObj['type'] = commonConfig.codeTagType.variable;
      resObj['codeStyle'] = commonConfig.codingStyle.ascii;
      resObj['length'] = newSeparatorList[1];
      return resObj;
    }

    if (~item.indexOf('S') && ~item.indexOf('|')) {
      const newSeparatorList = item.split('|');
      resObj['value'] = initItem;
      resObj['key'] = newSeparatorList[0];
      resObj['type'] = commonConfig.codeTagType.redundancy;
      resObj['codeStyle'] = commonConfig.codingStyle.ascii;
      resObj['length'] = (newSeparatorList[1] !== '?') ? parseInt(newSeparatorList[1]) : newSeparatorList[1];
      return resObj;
    }

    if (item.includes('#')) {
      if (item.includes('|')) {
        const seSeparatorList = item.split('|');
        const tagKey = seSeparatorList[0];
        if (tagKey.length > 1 && tagKey.slice(0, 2) === commonConfig.specialTags.length) {
          const lengthArr = seSeparatorList[0].split('L');
          resObj['type'] = commonConfig.codeTagType.length;
          resObj['codeStyle'] = commonConfig.codingStyle.hex;
          resObj['length'] = parseInt(lengthArr[1]) * 2;
          resObj['value'] = parseInt(seSeparatorList[1]);
          return resObj;
        }
        resObj['value'] = tagKey; // 附加value
        switch (tagKey) {
          case commonConfig.specialTags.seq:
            resObj['type'] = commonConfig.codeTagType.seqNum;
            resObj['codeStyle'] = commonConfig.codingStyle.hex;
            resObj['length'] = parseInt(seSeparatorList[1]) * 2;
            return resObj;
          case commonConfig.specialTags.crc_or:
            resObj['type'] = commonConfig.codeTagType.crcCheck;
            resObj['key'] = commonConfig.specialTags.crc_or;
            resObj['codeStyle'] = commonConfig.codingStyle.hex;
            resObj['length'] = 2;
            resObj['tagLength'] = parseInt(seSeparatorList[1]);
            return resObj;
          case commonConfig.specialTags.crc16:
            resObj['type'] = commonConfig.codeTagType.crcCheck;
            resObj['key'] = commonConfig.specialTags.crc16;
            resObj['codeStyle'] = commonConfig.codingStyle.hex;
            resObj['length'] = 4;
            resObj['tagLength'] = parseInt(seSeparatorList[1]);
            resObj['byteOrder'] = (seSeparatorList.length > 2) ? seSeparatorList[2] : 'AB';
            return resObj;
          case commonConfig.specialTags.crc8:
            resObj['type'] = commonConfig.codeTagType.crcCheck;
            resObj['key'] = commonConfig.specialTags.crc8;
            resObj['codeStyle'] = commonConfig.codingStyle.hex;
            resObj['length'] = 2;
            resObj['tagLength'] = parseInt(seSeparatorList[1]);
            return resObj;
          case commonConfig.specialTags.crc16xmodem:
          case commonConfig.specialTags.crc16IBM:
          case commonConfig.specialTags.crc16ccitt:
            resObj['type'] = commonConfig.codeTagType.crcCheck;
            resObj['key'] = tagKey;
            resObj['codeStyle'] = commonConfig.codingStyle.hex;
            resObj['length'] = 4;
            resObj['tagLength'] = parseInt(seSeparatorList[1]);
            resObj['byteOrder'] = (seSeparatorList.length > 2) ? seSeparatorList[2] : 'AB';
            return resObj;
          case commonConfig.specialTags.crc_xor:
            resObj['type'] = commonConfig.codeTagType.crcCheck;
            resObj['key'] = commonConfig.specialTags.crc_xor;
            resObj['codeStyle'] = commonConfig.codingStyle.hex;
            resObj['length'] = 2;
            resObj['tagLength'] = parseInt(seSeparatorList[1]);
            return resObj;
          default:
            break;
        }
      } else {
        switch (item) {
          case commonConfig.specialTags.crc16:
            resObj['type'] = commonConfig.codeTagType.crcCheck;
            resObj['key'] = commonConfig.specialTags.crc16;
            resObj['codeStyle'] = commonConfig.codingStyle.hex;
            resObj['length'] = 4;
            return resObj;
          case commonConfig.specialTags.crc8:
            resObj['type'] = commonConfig.codeTagType.crcCheck;
            resObj['key'] = commonConfig.specialTags.crc8;
            resObj['codeStyle'] = commonConfig.codingStyle.hex;
            resObj['length'] = 2;
            return resObj;
          case commonConfig.specialTags.crc16xmodem:
            resObj['type'] = commonConfig.codeTagType.crcCheck;
            resObj['key'] = commonConfig.specialTags.crc16xmodem;
            resObj['codeStyle'] = commonConfig.codingStyle.hex;
            resObj['length'] = 4;
            return resObj;
          case commonConfig.specialTags.crc16ccitt:
            resObj['type'] = commonConfig.codeTagType.crcCheck;
            resObj['key'] = commonConfig.specialTags.crc16ccitt;
            resObj['codeStyle'] = commonConfig.codingStyle.hex;
            resObj['length'] = 4;
            return resObj;
          case commonConfig.specialTags.crc_xor:
            resObj['type'] = commonConfig.codeTagType.crcCheck;
            resObj['key'] = commonConfig.specialTags.crc_xor;
            resObj['codeStyle'] = commonConfig.codingStyle.hex;
            resObj['length'] = 2;
            return resObj;
          default:
            break;
        }
      }
    }
  });
  modelList.forEach((item, index) => {
    if (item !== undefined) {
      if (item.hasOwnProperty('type') && item['type'] === commonConfig.codeTagType.nLoop) {
        const tagNums = parseInt(item['length'].toString());
        for (let newIdx = index + 1; newIdx <= (index + tagNums); newIdx++) {
          if(newIdx < modelList.length){
            modelList[newIdx]['isLoop'] = true;
          }
        }
        if ((tagNums + index + 1) < (modelList.length)) {
          modelList[tagNums + index + 1]["isEndLoop"] = true;
        }
      }
    }
  });

  const funcPattern = new RegExp(/(\##).*?(\##)/g);
  const funcArray = model.match(funcPattern) || [];
  funcArray.forEach((funcItem) => {
    const resObj = {};
    resObj['value'] = funcItem;
    resObj['key'] = funcItem.slice(2, funcItem.length - 2);
    resObj['type'] = commonConfig.codeTagType.systemFunc;
    modelList.push(resObj);
  });
  // console.log('##### modelList #####', modelList);
  return modelList;
}

// 判读是否为特殊标签，需要设置 commandMap
export function judgeSpecialTag(tag = {}) {
  return tag.type === commonConfig.codeTagType.variable
    || tag.type === commonConfig.codeTagType.nLoop
    || tag.type === commonConfig.codeTagType.systemFunc
}

// 获取组件的name和ports和states
export function getAtomicAttr(atomicId, type) {
  const atomicWidget = WidgetFactory.getWidgetById(atomicId);
  if (type === 'name') {
    if (!atomicWidget) return "";
    return atomicWidget.name || "";
  } else if (type === 'ports') {
    if (!atomicWidget) return [];
    return atomicWidget.ports.values || [];
  } else if (type === 'states') {
    if (!atomicWidget) return [];
    return atomicWidget.UI.states || [];
  }else if (type === 'events') {
    if (!atomicWidget) return [];
    return atomicWidget.ports.events || [];
  }
}

// 动态根据设备id加载设备命令
export function findDeviceCommands(deviceId) {
  const commandList = this.deviceList.find((item) => {
    return item._id === deviceId;
  });
  return commandList ? commandList.rspStatus : [];
}

// 当前命令的当前参数
export function findCommandParams(deviceId, command) {
  const commandList = this.findDeviceCommands(deviceId);
  const paramsList = commandList.find((item) => {
    return item.methodName === command;
  });
  return paramsList.params || [];
}
// 封装嵌套多层对象下是否包含指定值
export  function findObjectByValue(obj, value) {
  for (const key in obj) {
    if (obj[key] === value) {
      return true;
    } else if (typeof obj[key] === 'object' || Array.isArray(obj[key])) {
      if (findObjectByValue(obj[key], value)) {
        return true;
      }
    }
  }
  return false;
}
//修改渐变色
export function formatLinearColor(val) {
  const colorCfg = directionData.find((item) => {
    return item.key === val
  }) || {};
  return colorCfg.value || val
}
export function formatFontSize(type,size) {
  if(type==='large'){
    return Math.floor(size*1.2)
  }else if(type==='normal'){
    return size
  }else if(type==='small'){
    return Math.floor(size*0.8)
  }else if(type==='icon'){
    return Math.floor(size*1.5)
  }
}
export function hasAnyEmptyProperty(array, prop) {
  return array.some(item =>
    item[prop] === undefined ||
    item[prop] === null ||
    item[prop] === ''
  );
}
//将jsonSchema转换为json数据
export function parseSchemaRecursive(schema, field) {
  const node = {
    filed: field,
    type: schema.type,
    title: schema.title || '',
    description: schema.description || '',
    xMock: schema['x-mock'] || '',
    isRequired: false,
    id: generateUID(),
    isArrayItem:schema.isArrayItem,
    children: []
  };

  // 处理 object 类型
  if (schema.type === 'object' && schema.properties) {
    Object.keys(schema.properties).forEach(key => {
      const childSchema = schema.properties[key];
      const childNode = parseSchemaRecursive(childSchema, key);
      childNode.isRequired = schema.required ? schema.required.includes(key) : false;

      node.children.push(childNode);
    });
  }

  // 处理 array 类型 是object
  else if (schema.type === 'array' && schema.items && schema.items.type === 'object' && schema.items.properties) {
    const itemsNode={
      filed: 'items',
      type: schema.items.type,
      description: schema.items.description || '',
      id: generateUID(),
      isArrayItem: true,
      children: []
    }
    node.children.push(itemsNode)
    Object.keys(schema.items.properties).forEach(key => {
      const childSchema = schema.items.properties[key];
      const childNode = parseSchemaRecursive(childSchema, key);
      childNode.isRequired = schema.items.required ? schema.items.required.includes(key) : false;
      itemsNode.children.push(childNode);
    });
  }
  //处理array类型只有一个子元素
  else if (schema.type === 'array' && schema.items && schema.items.type !== 'object') {
    node.children.push({
      filed: 'items',
      type: schema.items.type,
      title: schema.items.title || '',
      description: schema.items.description || '',
      xMock: schema.items['x-mock'] || '',
      isRequired: false,
      id: generateUID(),
      isArrayItem:true,
      children: []
    })
  }
    return node;
}
export function  parseSchema(jsonSchema) {
  const schema = JSON.parse(jsonSchema);
  // 创建根节点
  const rootNode = {
    type: schema.type,
    filed: '根节点',  // 固定为 root
    title: schema.title,      // 根节点的 title 不需要显示
    mock: schema.mock,
    description: schema.description,
    id: generateUID(),
    isRoot: true,
    children: []
  };
  // 处理 properties
  if (schema.properties) {
    Object.keys(schema.properties).forEach(key => {
      const childSchema = schema.properties[key];
      const childNode = parseSchemaRecursive(childSchema, key);
      childNode.isRequired = schema.required ? schema.required.includes(key) : false;
      rootNode.children.push(childNode);
    });
  }
  return rootNode;
}
//将数据生成jsonSchema
export function convertToSchema(node) {
  const schema = {...node,};
  // 设置类型
  // 处理mock属性：优先使用mock，否则使用xMock
  if (node.xMock && node.xMock.length > 0) {
    schema['x-mock'] = node.xMock;
  }
  delete schema.children;
  delete schema.id;
  delete schema.isRequired;
  delete schema.isRoot;
  delete schema.filed;
  delete schema.xMock;
  // 处理对象类型
  if (node.type === 'object' && node.children)  {
    schema.properties = {};
    schema.required = [];
    node.children.forEach(child => {
      schema.properties[child.filed] = convertToSchema(child);
      if (child.isRequired) {
        schema.required.push(child.filed);
      }
    });
  }
  // 处理数组类型
  else if (node.type === 'array' && node.children) {
    node.children.forEach(child => {
      if(child.type!=='object'){
        schema.items = {};
          schema.items.description =child.description ;
          schema.items.type =child.type ;
      }else{
        schema.items = {};
        schema.items.type = 'object';
        schema.items.description = child.description;
        schema.items.properties = {};
        schema.items.required = [];
        child.children.forEach(child => {
          schema.items.properties[child.filed] = convertToSchema(child);
          if (child.isRequired)
            schema.items.required.push(child.filed);
          });
      }
    });
  }
  return schema;
}
//将jsonschema转换成单一的schema，只带类型的
export function generateSchema(schema) {

  // 处理基本类型
  if (schema.type === 'string') return 'string';
  if (schema.type === 'number') return 0;
  if (schema.type === 'integer') return 0;
  if (schema.type === 'boolean') return false;
  if (schema.type === 'null') return null;
  // 处理数组类型
  if (schema.type === 'array') {
    // 如果数组元素是对象
    const exampleItem = generateSchema(schema.items);
    return [exampleItem];
  }
  // 处理对象类型
  if (schema.type === 'object') {
    const obj = {};
    for (const [key, propSchema] of Object.entries(schema.properties || {})) {
      obj[key] = generateSchema(propSchema);
    }
    return obj;
  }
  return 'unknown_type';
}
